/*
 * ============================================================================
 * Copyright Notice!
 * ----------------------------------------------------------------------------
 * This file contains proprietary and confidential information belonging to the
 * group of people involvled in developing this project.  Reproduction, disclosure 
 * or use without specific written authorization from project stake holders is 
 * prohibited. Please refer the readme.txt in project installation folder for more
 * specific contacts
 *
 * All rights reserved.
 * ============================================================================
 */
package edu.uwm.universitydb.service.project;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import edu.uwm.universitydb.dao.coinvestigate.CoInvestigatorInsertCommand;
import edu.uwm.universitydb.dao.coinvestigate.DeleteCoInvestigatorCommand;
import edu.uwm.universitydb.dao.professor.GetProjectCoInvestigatorsCommand;
import edu.uwm.universitydb.dao.professor.GetProjectManagerCommand;
import edu.uwm.universitydb.dao.project.DeleteProjectCommand;
import edu.uwm.universitydb.dao.project.InsertProjectCommand;
import edu.uwm.universitydb.dao.project.RetrieveAllProjectsCommand;
import edu.uwm.universitydb.dao.project.SearchProjectByIDCommand;
import edu.uwm.universitydb.dao.project.SearchProjectByManagerCommand;
import edu.uwm.universitydb.dao.project.UpdateProjectCommand;
import edu.uwm.universitydb.dao.project.management.DeleteProjectManagementAssociationCommand;
import edu.uwm.universitydb.dao.project.management.FetchProjectManagerIdCommand;
import edu.uwm.universitydb.dao.project.management.InsertProjectManagementAssociationCommand;
import edu.uwm.universitydb.dao.project.management.UpdateProjectManagementAssociationCommand;
import edu.uwm.universitydb.dao.project.member.DeleteProjectMemeberCommand;
import edu.uwm.universitydb.dao.project.member.InsertProjectMemberCommand;
import edu.uwm.universitydb.dao.student.SearchStudentsByProjectId;
import edu.uwm.universitydb.db.connection.DBConnectionFactory;
import edu.uwm.universitydb.framework.exception.DataAccessException;
import edu.uwm.universitydb.model.Professor;
import edu.uwm.universitydb.model.Project;
import edu.uwm.universitydb.model.Role;
import edu.uwm.universitydb.model.Student;
import edu.uwm.universitydb.model.User;

/**
 * <code>ProjectServiceImpl</type>
 * 
 * Implementation class for the interface Project Service
 * 
 * @author Shyam Nair
 */
public class ProjectServiceImpl implements ProjectService
{

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#createProject(edu.uwm.universitydb.model.Project, edu.uwm.universitydb.model.Professor)
     */
    @Override
    public boolean createProject(final Project project, final Professor manager)
        throws DataAccessException
    {
        // connection
        Connection dbConnection = null;
        try
        {
            // obtain a connection from factory
            final DBConnectionFactory connectionFactory = DBConnectionFactory.getInstance();
            dbConnection = connectionFactory.getDBConnection();
            dbConnection.setAutoCommit(false);

            // Insert Project
            final InsertProjectCommand projectInsertCommand = new InsertProjectCommand(project);
            int insertCount = projectInsertCommand.executeCommand(dbConnection);

            if ((insertCount > 0) && (manager != null))
            {
                // create an association if manger id is not null
                final String managerSSN = manager.getSsnNum();
                if ((managerSSN != null) && !("".equals(managerSSN)))
                {
                    final Integer projectNum = project.getProjectNum();
                    final InsertProjectManagementAssociationCommand insertAssociationCommand =
                        new InsertProjectManagementAssociationCommand(managerSSN, projectNum);
                    insertCount = insertAssociationCommand.executeCommand(dbConnection);
                }
            }

            // commit
            dbConnection.commit();
            return (insertCount > 0) ? true : false;

        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            try
            {
                dbConnection.rollback();
            }
            catch (final SQLException sqlEx)
            {
                sqlEx.printStackTrace();
            }
            return false;
        }
        catch (final SQLException e)
        {
            e.printStackTrace();
            try
            {
                dbConnection.rollback();
            }
            catch (final SQLException sqlEx)
            {
                sqlEx.printStackTrace();
            }
            return false;
        }
        finally
        {
            if (dbConnection != null)
            {
                try
                {
                    dbConnection.close();
                }
                catch (final SQLException e)
                {
                    // DO NOTHING
                    e.printStackTrace();
                }
            }
        }
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#associateCoInvestigator(java.lang.String, java.lang.Integer)
     */
    @Override
    public boolean associateCoInvestigator(final String managerSSN, final Integer projectNum)
    {
        try
        {
            final CoInvestigatorInsertCommand insertCommand =
                new CoInvestigatorInsertCommand(managerSSN, projectNum);
            final int insertCount = insertCommand.executeCommand();
            return (insertCount > 0) ? true : false;
        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#removeCoInvestigator(java.lang.String, java.lang.Integer)
     */
    @Override
    public boolean removeCoInvestigator(final String managerSSN, final Integer projectNum)
    {
        try
        {
            final DeleteCoInvestigatorCommand deleteCommand =
                new DeleteCoInvestigatorCommand(managerSSN, projectNum);
            return (deleteCommand.executeCommand() > 0);
        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            return false;
        }
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#associateProjectWithManager(java.lang.String, java.lang.Integer)
     */
    @Override
    public boolean associateProjectWithManager(final String managerSSN, final Integer projectNum)
    {
        // connection
        Connection dbConnection = null;
        try
        {
            // obtain a connection from factory
            final DBConnectionFactory connectionFactory = DBConnectionFactory.getInstance();
            dbConnection = connectionFactory.getDBConnection();
            dbConnection.setAutoCommit(false);

            // check if an association already exists
            final FetchProjectManagerIdCommand projectManagerFetchCommand =
                new FetchProjectManagerIdCommand(projectNum);
            final String managerId = projectManagerFetchCommand.executeCommand(dbConnection);

            if ((managerId == null) || "".equals(managerId))
            {
                // if is no manager .. create one
                final InsertProjectManagementAssociationCommand insertAssociationCommand =
                    new InsertProjectManagementAssociationCommand(managerSSN, projectNum);
                insertAssociationCommand.executeCommand(dbConnection);
            }
            else
            {
                // manager exists update
                final UpdateProjectManagementAssociationCommand updateCommand =
                    new UpdateProjectManagementAssociationCommand(managerSSN, projectNum);
                updateCommand.executeCommand(dbConnection);
            }

            // commit
            dbConnection.commit();
            return true;

        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            try
            {
                dbConnection.rollback();
            }
            catch (final SQLException sqlEx)
            {
                sqlEx.printStackTrace();
            }
            return false;
        }
        catch (final SQLException e)
        {
            e.printStackTrace();
            try
            {
                dbConnection.rollback();
            }
            catch (final SQLException sqlEx)
            {
                sqlEx.printStackTrace();
            }
            return false;
        }
        finally
        {
            if (dbConnection != null)
            {
                try
                {
                    dbConnection.close();
                }
                catch (final SQLException e)
                {
                    // DO NOTHING
                    e.printStackTrace();
                }
            }
        }
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#searchProjectByManager(java.lang.String)
     */
    @Override
    public List<Project> searchProjectByManager(final String profSSN)
    {
        return searchProjectByManager(profSSN, ProjectSortOrderEnum.PROJECTNUM);
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#searchProjectByManager(java.lang.String, edu.uwm.universitydb.service.project.ProjectSortOrderEnum)
     */
    @Override
    public List<Project> searchProjectByManager(final String profSSN,
        final ProjectSortOrderEnum sortOrderEnum)
    {
        try
        {
            final SearchProjectByManagerCommand searchCommand =
                new SearchProjectByManagerCommand(profSSN, sortOrderEnum);
            return searchCommand.executeCommand();
        }
        catch (final DataAccessException ex)
        {
            ex.printStackTrace();
        }
        return null;
    }

    @Override
    public Project searchProjectByID(final Integer id)
    {
        try
        {
            final SearchProjectByIDCommand searchCommand = new SearchProjectByIDCommand(id);
            return searchCommand.executeCommand();
        }
        catch (final DataAccessException ex)
        {
            ex.printStackTrace();
        }
        return null;
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#getAllProjects()
     */
    @Override
    public List<Project> getAllProjects()
    {
        return getAllProjects(ProjectSortOrderEnum.PROJECTNUM);
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#getAllProjects(edu.uwm.universitydb.service.project.ProjectSortOrderEnum)
     */
    @Override
    public List<Project> getAllProjects(final ProjectSortOrderEnum sortOrder)
    {
        try
        {
            final RetrieveAllProjectsCommand searchCommand =
                new RetrieveAllProjectsCommand(sortOrder);
            return searchCommand.executeCommand();
        }
        catch (final DataAccessException ex)
        {
            ex.printStackTrace();
        }
        return null;
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#getProjectsByUser(edu.uwm.universitydb.model.User)
     */
    @Override
    public List<Project> getProjectsByUser(final User user, final String userSSN)
    {
        return getProjectsByUser(user, userSSN, ProjectSortOrderEnum.PROJECTNUM);
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#getProjectsByUser(edu.uwm.universitydb.model.User, edu.uwm.universitydb.service.project.ProjectSortOrderEnum)
     */
    @Override
    public List<Project> getProjectsByUser(final User user, final String userSSN,
        final ProjectSortOrderEnum sortOrder)
    {
        final Role role = user.getRole();
        if (Role.ADMINISTRATOR.equals(role))
        {
            return getAllProjects(sortOrder);
        }
        else
        {
            return searchProjectByManager(userSSN, sortOrder);
        }
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#removeProject()
     */
    @Override
    public boolean removeProject(final Integer projectNumber)
    {
        // connection
        Connection dbConnection = null;
        try
        {
            // obtain a connection from factory
            final DBConnectionFactory connectionFactory = DBConnectionFactory.getInstance();
            dbConnection = connectionFactory.getDBConnection();
            dbConnection.setAutoCommit(false);

            // Delete Project Associations
            final DeleteProjectManagementAssociationCommand deleteAssociationCmd =
                new DeleteProjectManagementAssociationCommand(projectNumber);
            int insertCount = deleteAssociationCmd.executeCommand(dbConnection);

            final DeleteProjectCommand deleteCmd = new DeleteProjectCommand(projectNumber);
            insertCount = deleteCmd.executeCommand(dbConnection);

            // commit
            dbConnection.commit();
            return (insertCount > 0) ? true : false;

        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            try
            {
                dbConnection.rollback();
            }
            catch (final SQLException sqlEx)
            {
                sqlEx.printStackTrace();
            }
            return false;
        }
        catch (final SQLException e)
        {
            e.printStackTrace();
            try
            {
                dbConnection.rollback();
            }
            catch (final SQLException sqlEx)
            {
                sqlEx.printStackTrace();
            }
            return false;
        }
        finally
        {
            if (dbConnection != null)
            {
                try
                {
                    dbConnection.close();
                }
                catch (final SQLException e)
                {
                    // DO NOTHING
                    e.printStackTrace();
                }
            }
        }
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#getProjectManager()
     */
    @Override
    public Professor getProjectManager(final Integer pno)
    {
        try
        {
            final GetProjectManagerCommand searchCommand = new GetProjectManagerCommand(pno);
            return searchCommand.executeCommand();
        }
        catch (final DataAccessException ex)
        {
            ex.printStackTrace();
        }
        return null;
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#updateProject()
     */
    @Override
    public boolean updateProject(final Project project) throws DataAccessException
    {
        final UpdateProjectCommand updateCommand = new UpdateProjectCommand(project);
        final int updateCount = updateCommand.executeCommand();
        return (updateCount > 0) ? true : false;
    }

    /*
     * (non-javadoc)
     * @see edu.uwm.universitydb.service.project.ProjectService#getProjectCoinvestigators()
     */
    @Override
    public List<Professor> getProjectCoinvestigators(final Integer projectNumber)
    {
        try
        {
            final GetProjectCoInvestigatorsCommand searchCommand =
                new GetProjectCoInvestigatorsCommand(projectNumber);
            return searchCommand.executeCommand();
        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public List<Student> getProjectStudents(final Integer projectNumber)
    {
        try
        {
            final SearchStudentsByProjectId searchCommand =
                new SearchStudentsByProjectId(String.valueOf(projectNumber));
            return searchCommand.executeCommand();
        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean removeStudentFromProject(final String studentSSN, final Integer projectNum)
    {
        try
        {
            final DeleteProjectMemeberCommand deleteCommand =
                new DeleteProjectMemeberCommand(studentSSN, String.valueOf(projectNum));
            return (deleteCommand.executeCommand() > 0);
        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean associateProjectWithStudent(final String studentSSN, final Integer projectNum)
    {
        try
        {
            final InsertProjectMemberCommand insertCommand =
                new InsertProjectMemberCommand(studentSSN, String.valueOf(projectNum));
            return (insertCommand.executeCommand() > 0);
        }
        catch (final DataAccessException e)
        {
            e.printStackTrace();
            return false;
        }
    }

}

/*
 * ============================================================================
 * Change History
 * ----------------------------------------------------------------------------
 * Apr 19, 2014   Shyam Nair
 * File created
 * ----------------------------------------------------------------------------
 * Apr 23, 2014 Shyam Nair
 * Added methods - associateCoInvestigator, removeCoInvestigator
 * ----------------------------------------------------------------------------
 * Apr 30, 2014 Shyam Nair
 * Added methods - associateStudents, removeStudents
 * ----------------------------------------------------------------------------
 */